`ifndef CACHE_DEFINE_H
`define CACHE_DEFINE_H

// cache参数
`define WAY_SIZE 32 // 组大小（Byte）
`define CACHELINE_SIZE 4 // 行大小（Byte）// 限制cacheline中block的大小为一个字，不然会导致每次axi传输都是narrow transfer

`define WAY_NUM 2 // 每个cache的组数
`define CACHELINE_NUM (`WAY_SIZE / `CACHELINE_SIZE) // 每个组的行数


// 计算地址宽度
`define ADDR_WIDTH 32 // 总地址宽度
`define OFFSET_WIDTH ($clog2(`CACHELINE_SIZE))
`define INDEX_OFFSET_WIDTH ($clog2(`WAY_SIZE))
`define INDEX_WIDTH `INDEX_OFFSET_WIDTH - `OFFSET_WIDTH
`define TAG_WIDTH `ADDR_WIDTH - `INDEX_OFFSET_WIDTH


typedef logic [`TAG_WIDTH-1:0] tag_t;
typedef logic [`INDEX_WIDTH-1:0] index_t;
typedef logic [`OFFSET_WIDTH-1:0] offset_t;
typedef struct packed {
    tag_t tag;
    index_t index;
    offset_t offset;
} iaddr_t;


typedef logic [`CACHELINE_SIZE-1:0] idata_t;
typedef struct packed {
    // logic dirty; // icache无写回策略，不需要维护脏位
    logic valid;
    tag_t tag;
    ysyx_data_t data;
} icacheline_t;


typedef icacheline_t [`CACHELINE_NUM-1:0] set_t;
typedef struct packed {
    set_t set0;
    set_t set1;
} icache_t;

typedef enum logic [2:0] {
    C_IDLE, // 空闲状态/命中状态
    LOOKUP, // 查找状态，在每个set中，用index找到若干个cacheline，并同时用tag进行比较。若命中，则->C_IDLE；若未命中，则->MISS
    MISS,   // 未命中状态，使用替换算法选出一个牺牲行，判断该行是否需要写回。若需要，则->WRITEBACK；若不需要，则->READ_ALO
    WRITEBACK, // 写回状态，向RAM发出写请求，然后->READ_ALO
    READ_ALO // 读分配状态，RAM返回数据后，进行cacheline替换，同时将数据返回给cpu
} icstate_t;

`endif
